home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-11-16 | 55.2 KB | 1,387 lines |
- MiNT is Now TOS: A Multitasking OS Extension for the Atari ST/TT/Falcon
-
- The MiNT kernel is derived from MiNT, Copyright 1990,1991,1992 Eric R.
- Smith. All rights reserved. Used and modified by Atari under license from
- Eric Smith; new code and features Copyright 1992,1993,1994 Atari Corporation.
-
-
- Introduction
-
-
- MiNT is a replacement for (most of) GEMDOS. It is designed to provide
- the same kind of services as GEMDOS (file and process management,
- primarily) but with extensions to permit such things as multitasking,
- interprocess communication, job control, and a flexible file system
- interface that permits loadable file systems and device drivers.
-
- This document does not discuss the new, multitasking Desktop or utility
- programs such as MINIWIN or TCSH. Refer to other documents for
- descriptions of these programs.
-
- MiNT exists to make your job as a developer easier. You can use MiNT
- system calls to do things like run background processes, to set up
- interprocess communication, to examine files on disk, or in more
- advanced applications to install new kinds of device drivers or
- file systems. Your programs generally don't need to know about
- MiNT unless they want to take advantage of new MiNT features;
- the old GEMDOS calls are still supported for backwards compatibility.
-
- Our discussion of MiNT will begin with some of the changes visible
- to all users, and then continue with tips about programming MiNT.
-
-
- Pseudo Drives
-
-
- MiNT provides a fake "disk drive" called U: (for "unified"). There are
- "directories" in the root of this drive which contain "files" special to
- MiNT. These "files" are not real files, but may represent other objects
- such as devices or executing programs. Ordinary file-access calls are used
- to deal with them; for instance, writing to U:\DEV\CON is like writing to
- the console (as distinct from stdout).
-
- The following directories are available on U:
-
- U:\DEV
-
- Contains files which correspond to the BIOS devices; this allows
- you to access these devices from within programs. For example, saving an
- ASCII text file to "U:\DEV\PRN" should cause it to be printed on your
- printer.
-
- The following devices are available by default in U:\DEV (additional device
- drivers may be installed by applications):
-
- CENTR the Centronics (parallel) printer port
- MODEM1 the RS232 serial port
- MIDI midi port
- KBD intelligent keyboard controller
- PRN printer device (usually the parallel port)
- AUX auxiliary terminal (usually the rs232 port)
- CON current control terminal
- TTY same as CON
- STDIN current file handle 0 (standard input)
- STDOUT current file handle 1 (standard output)
- STDERR current file handle 2 (standard error)
- CONSOLE the keyboard/screen
- MOUSE the mouse (reserved for the operating system)
- NULL a null device (like Unix's /dev/null)
-
- The "STD*" file handles are useful for providing I/O redirection to programs
- that normally require file names on the command line, so you
- can run such a program in a pipeline.
-
-
- U:\PIPE
-
- Contains files which are FIFO queues (e.g. pipes). All files
- created in U:\PIPE are temporary; when the last program using a FIFO
- closes it, it is erased. Normally, U:\PIPE will be empty, but it will
- have items on it when you're running a window manager, print spooler,
- or similar program that uses FIFOs or pseudo-ttys for communication.
- (See the section on FIFOs later in this guide.)
-
- U:\PROC
-
- Contains special files that represent all currently executing processes,
- and their states (such as whether they're running, ready, or waiting, their
- process ID numbers, and the amount of memory they've taken.) The "files"
- will have names like "GEM.001"; this means that the process name is "GEM"
- (usually because it was started from a file like "GEM.SYS"), and its
- process ID is 1. You can rename processes just as if they were files,
- except that any extension you give is always replaced with the process ID
- (e.g. if you rename GEM.001 to FOO.BAR, it will really become
- FOO.001).
-
- The "size" of a process file is the amount of memory that is allocated to
- it. Note that this is the sum of all memory that the process may
- access. The entire size of a shared memory block will be added to every
- process which has access to the block. The date and time stamp of a
- process file is the data and time that the process was started. A process'
- current state is reflected by the attribute bits of the file; most of these
- are not visible from the Desktop, but can be checked by programs such
- as PS or TOP.
-
- Here are the attribute byte combinations for process files on U:\PROC,
- and their meanings:
-
- ATTRIBUTE PROCESS STATE
-
- 0x00 currently running
- 0x01 ready to run
- 0x20 waiting for an event
- 0x21 waiting for I/O
- 0x22 zombie (exited)
- 0x02 terminated and resident (TSR)
- 0x24 stopped by a signal
-
- The "zombie" state is for processes which have exited, but whose parents
- haven't yet learned their exit codes.
-
- Deleting a "file" in U:\PROC will send a SIGTERM signal to the
- corresponding process, which will usually result in that process being
- terminated. It is not possible to delete TSR or zombie processes.
-
-
- U:\SHM
-
- U:\SHM is a place for shared memory. Processes may create files
- in this directory which represent blocks of memory that they wish
- to share with other processes. This provides a very fast method
- of interprocess communication. (See the section on Shared Memory
- later in this guide.)
-
-
- Other directories on drive U: are actually other drives. U:\C is
- drive C:, so the file C:\MINT\MW.PRG, for instance, is also visible
- as U:\C\MINT\MW.PRG.
-
-
-
- Background Processes
-
-
- Programs may be started in the background. The easiest way to do this
- is with the MultiTOS desktop. It can also be done with CLIs such as
- TCSH or a similar shell. In TCSH you can say something like:
-
- % cd \foo\src
- % make >& errors &
-
- This runs "make" and redirects both its standard output and its error output
- to a file called errors. The final "&" means "in the background." The shell
- starts the program, then comes back for another command without waiting
- for the program to finish running.
-
- A background process that tries to write to the console will stop, which
- is why the example redirects the output of "make." In the shell, the
- command "fg" will bring a stopped process to the foreground. In addition,
- the command "stty -tostop" (read that as "set tty, no terminal-output stop")
- turns off the stop-on-output feature.
-
-
- Pipes
-
-
- Pipes are special files that are used to communicate between processes. The
- data in a pipe is always in memory, so using a pipe instead of a temporary
- file is usually faster; it also doesn't consume disk space. Only a limited
- amount of data can be held in a pipe at once; when a process tries to write
- more data, it is suspended until another process empties the pipe by reading
- some data. If there are no more readers, a process writing on a pipe is
- terminated. Writes of 1K or less to a pipe are atomic, that is, if you
- make an Fwrite call with 1024 or fewer bytes, these bytes are guaranteed
- to be written together; if you try to write more than 1024 bytes to a
- pipe, it's possible that your data will be interleaved with the data
- of some other process writing to the same pipe, or for a process reading from
- the pipe to get your data in chunks, rather than all at once.
-
- Again, with TCSH it is easy to demonstrate the use of pipes:
-
- % ls -lt | head
-
- This is a "pipeline." The first stage of the pipeline is the program "ls"
- which has "-lt" as its argument. That is, "list directory, long form,
- sorted by date (most recent first)." The output of "ls" is passed as input
- to the next stage of the pipeline, "head." This program displays only the
- first 10 lines of its input. The resulting output from this pipeline,
- then, is a listing of the 10 most-recent files in the current directory.
-
-
- Job Control
-
-
- MiNT supports job control. The ^Z (control-Z) key can be used to
- suspend a process. The process can be restarted again if it is sent the
- appropriate signal. TCSH sends this signal when you use the "fg"
- command. TCSH's "bg" command restarts stopped processes, too, but does
- so in the background, so they'll stop again if they attempt input or
- output. There is also a "delayed" suspend key, ^Y, that takes effect only
- when a process attempts to read it.
-
- Some programs written for TOS put the terminal in "raw" mode, where no
- control characters are interpreted. You can use CTRL-ALT-Z to achieve the
- effect of ^Z for such programs. However, this feature should be used with
- caution -- it's possible that the TOS program had a good reason for not
- wanting to be interrupted.
-
- More sophisticated job control facilities can be provided by shells that are
- specifically written with MiNT in mind. TCSH demonstrates this. Jobs
- run in the background from such shells are automatically stopped when
- they attempt to read from the terminal or write to it. Thus, you can run a
- long compile in the background, and if an error occurs and the compiler
- attempts to write on the screen, it will be stopped.
-
- Some other special keys that MiNT interprets are:
-
- CTRL-ALT-DEL
- Provides a (warm) boot, as in TOS >= 1.4; with the right shift key, you
- get a cold boot.
-
- Some other keys are recognized by MiNT if the process is doing I/O in
- "cooked" mode:
-
- ^C (CTRL-C)
- Interrupt the running program with signal SIGINT. This (usually)
- will kill the process, unless it has made arrangements to catch it.
- Note that ^C takes effect immediately under MiNT, whereas under TOS
- it only takes effect when the process reads or writes.
-
- ^\ (quit)
- Send a QUIT signal to a process; usually the same end result as ^C, but
- it is guaranteed to kill a TOS program (only MiNT-specific programs
- know how to catch it). Use with caution.
-
- These keys do \not\ have any effect on processes operating in "raw" mode,
- such as editors. However, you can force these to work even on such programs
- by holding down the ALT key as well, e.g. CTRL-ALT-C will always send SIGINT
- to the process. You should use caution when doing this, since some programs
- will function incorrectly and/or lose data if interrupted when they
- aren't expecting it.
-
-
- Testing for the Presence of MiNT
-
-
- The best way to check to see if MiNT is active is to check the cookie jar.
- MiNT installs a cookie of 0x4d694e54 (in ASCII, 'MiNT'), with a value
- consisting of the major/ minor version numbers in the high/low bytes of the
- low word. Thus, MiNT version 1.02 has a cookie value of 0x00000102L.
- (This isn't the place to explain the cookie jar, but basically it's a list
- of (cookie, value) pairs of longwords, terminated by cookie 0; a pointer to
- the jar is found at 0x5a0. MiNT always installs a cookie jar; versions of
- TOS prior to 1.6 don't always, in which case 0x5a0 will contain 0).
-
-
- File Handles and Devices
-
-
- File handle -1 refers to the current control terminal, \not\ necessarily
- the console (though this is where it points by default). BIOS handle 2 also
- refers to the control terminal, so that e.g. Bconout(2, c) outputs
- a character to the control terminal. Thus,
-
- Fforce(-1, Fopen("U:\\DEV\\MODEM1", 2));
- r = Bconin(2);
-
- reads a character from the RS232 port under MiNT. This is done so that
- programs that use the BIOS for I/O will be able to run in windows or
- over the modem. Similarly, the GEMDOS device CON: refers to the current
- control terminal, so Fopen("CON:", 2) is normally equivalent to Fdup(-1).
- To access the physical console, use device U:\DEV\CONSOLE (but do
- this only if you really, really need the output to go to the physical
- console; in almost all cases the output should be sent to the control
- terminal, since that's where the user will be expecting it to go).
-
- In a similar fashion, file handle -2 and bios device 1 (GEMDOS device AUX:)
- may be redirected away from the RS232 port (device U:\DEV\MODEM1), and
- file handle -3 and bios device 0 (GEMDOS device PRN:) may be directed away
- from the Centronics printer port (device U:\DEV\CENTR). Since both the
- GEMDOS handles and BIOS device numbers are redirected, any program at all
- will obey the redirection unless it accesses the hardware directly (or
- unless it was written for MiNT and specifically uses the new device names
- like U:\DEV\CENTR; this should be done only if \absolutely\ necessary!)
- See also the PRN= and CON= commands for mint.cnf, which provide another
- way to redirect the printer and console. (Actually, they're just another
- interface to the same method of redirection.)
-
- File handles -4 and -5 are new with MiNT, and refer to the MIDI input
- and output devices respectively. Redirecting these handles will affect
- BIOS operations on bios device 4 (the MIDI port). This is so
- programs that do MIDI I/O using BIOS device 4 can be connected in a special
- kind of pipeline.
-
-
- Programming with MiNT
-
- A file (MINTBIND.H) is provided that gives a C interface to the new
- MiNT system calls. Users of other programming languages will have to write
- the interfaces themselves. This should be relatively straightforward, so
- long as your compiler provides a way to call GEMDOS directly.
-
-
- Interprocess Communication
-
-
- MiNT provides many forms of interprocess communication (IPC): signals, fifos,
- shared memory, message passing, and semaphores.
-
- Signals
-
-
- MiNT introduces the new (to TOS) concept of a signal. If you're
- familiar with Unix/Posix signals, then MiNT signals will will be
- easy to learn; but note that there are some (not so subtle) differences
- between MiNT and Unix!
-
- A signal is a small non-negative integer that represents an exceptional event;
- usually something that is very urgent. It's somewhat like an interrupt or
- exception to the CPU, only it's implemented in the operating system
- instead of in the hardware. Like many exceptions (bus errors, etc.) signals
- are usually fatal. Most signals can be caught by programs (so that a
- program-defined routine is called) or ignored; if a signal is caught or
- ignored, it is no longer fatal. Signals can also be blocked; a
- blocked signal is not acted upon until it is unblocked.
-
- A signal is said to be sent to a process when the exceptional
- condition related to that signal occurs, or when another process sends
- the signal with the Pkill() system call. The signal is said to
- be delivered to the process when that process wakes up and
- begins to take whatever actions are appropriate for the signal. Note
- that there may be a considerable time interval between the sending of
- a signal and its delivery. For example, if process A has blocked the
- SIGHUP signal (signal 1), then no SIGHUP will be delivered to it until
- it has unblocked that signal, even if process B sends it SIGHUP with
- the Pkill() system call. Note also that a signal is not
- necessarily delivered the same number of times that it is sent. If both
- process B and process C send SIGHUP to process A, when process A
- unblocks SIGHUP only one SIGHUP will be delivered. This is because signals
- are like flags; once a flag has been set (the signal is sent) setting
- the flag again will have no effect until it has been cleared (the signal
- is delivered).
-
- What Signals Are There?
-
- There are 32 possible signals, 0-31. Not all of these have been assigned
- a meaning under MiNT. Here are the ones that have been given a meaning;
- we give the symbolic name for the signal, the corresponding integer,
- and the "traditional" meaning for the process that the signal is sent to.
- Any signal not listed here should be considered as "reserved" and should not
- be used by applications.
-
- Unless otherwise noted, the default action for signals is to terminate
- the process.
-
- #define SIGNULL 0 /* No default action */
- This isn't really a signal at all; it is never delivered to processes
- and has no effect. It exists only so that processes can test to see if
- a particular child process has exited, by attempting to send SIGNULL
- to the child. If the child exists, the attempt will succeed but nothing
- will be done. If the child has terminated, the caller will get an error.
- It is not possible to catch or block this signal, since it is never
- sent to processes anyway.
-
- #define SIGHUP 1
- "The terminal that you're connected to is no longer valid." This signal
- is commonly sent by, for example, window managers when the user has
- closed the window. Processes should not attempt any I/O to their
- controlling terminal after receiving this signal, and indeed should probably
- exit unless the user has specifically asked them to continue.
-
- #define SIGINT 2
- "Please stop what you're doing." This signal is sent when the user presses
- control-C. It usually means that the user wishes the process to stop its
- current task. Non-interactive processes should generally exit when they
- receive this signal; interactive processes may wish to catch SIGINT
- so that the user can use it to break out of time-consuming tasks and
- return to a command prompt.
-
- #define SIGQUIT 3
- "Stop what you're doing, something's gone wrong!" This signal is sent when
- the user presses control-\. It usually indicates a desire to immediately
- abort the process because of an error that the user has noticed. It is
- generally thought to be "stronger" than SIGINT, and exiting (perhaps after
- cleaning up data structures) is an appropriate response to this.
-
- #define SIGILL 4
- "An illegal instruction has been encountered." This corresponds to the
- 680x0 illegal instruction trap, and usually indicates a very serious error;
- catching this signal is generally unwise.
-
- #define SIGTRAP 5
- "The single-step trace trap has been encountered." This corresponds to the
- 680x0 trace trap, and is usually activated (and handled) by debuggers;
- user programs shouldn't catch this.
-
- #define SIGABRT 6
- "An awful error has occured." This is commonly sent by the abort library
- function, and indicates that something has gone very, very wrong (for
- example, data structures have been unexpectedly corrupted). It is unlikely
- that anything useful can be done after this signal is sent; programs
- should not normally catch or ignore SIGABRT.
-
- #define SIGPRIV 7
- "Privilege violation." An attempt has been made to execute an instruction
- in user mode that is normally restricted to supervisor mode; this corresponds
- to the 680x0 privilege violation exception, and indicates a serious error.
-
- #define SIGFPE 8
- "Division by zero or a floating point error has occured." Processes may
- ignore or catch this signal (which corresponds to the 680x0 division by zero
- trap) and deal with it as they see fit.
-
- #define SIGKILL 9 /* Cannot be blocked or caught */
- "Die!" This signal will never be seen by a process; nor can processes
- block it. Sending SIGKILL is a way to be sure of killing a run-away
- process. Use it only as a last resort, since it gives the process no
- chance to clean up and exit gracefully.
-
- #define SIGBUS 10
- "Bus error." Corresponds to the 680x0 bus error exception, and indicates
- a very serious error; programs should generally not attempt to ignore
- or catch this signal.
-
- #define SIGSEGV 11
- "Illegal memory reference." Corresponds to the 680x0 address error
- exception, and indicates a very serious error; catching or ignoring this
- signal is not recommended.
-
- #define SIGSYS 12
- "Bad argument to a system call." This signal is sent when an illegal
- (usually, out of range) parameter is sent to a system call, and when that
- system call does not have any "nice" way to report errors. For example,
- Super(0L) when the system is already in supervisor mode causes SIGSYS to
- be raised. Note that the kernel does not always detect illegal/out of
- range arguments to system calls, only sometimes.
-
- #define SIGPIPE 13
- "A pipe you were writing to has no readers." Programs may catch this signal
- and attempt to exit gracefully after receiving it; note that exiting is
- appropriate because the standard output is probably no longer connected
- to anything.
-
- #define SIGALRM 14
- "The alarm you set earlier has happened." This signal is sent to processes
- when the alarm clock set by Talarm (q.v.) expires. It's very
- common to catch this signal and from the signal handler jump to a known
- point in the program; for example, to indicate a timeout while attempting
- to communicate over a serial line.
-
- #define SIGTERM 15
- "Please die." This is a polite form of SIGKILL (#9). Programs should
- respect this nice request; they may want to catch the signal to perform
- some cleanup actions, but they should then exit (since if they don't,
- the user will probably get mad and send SIGKILL later anyway...). This
- is the signal that is sent when a process is dragged to the trashcan on
- the desktop.
-
- #define SIGSTOP 17 /* Default action: suspend the process */
- "Suspend yourself." This signal is sent to a process when it should be
- stopped temporarily. SIGSTOP is used primarily by debuggers and similar
- programs; suspensions requested directly by the user usually are signalled
- by SIGTSTP (q.v.) This signal cannot be ignored, blocked, or caught.
-
- #define SIGTSTP 18 /* Default action: suspend the process */
- "The user is asking you to suspend yourself." This signal is sent immediately
- when the user presses the control-Z key, and is sent when the process tries
- to read a control-Y key in cooked mode (for a delayed stop). In both cases,
- the process should suspend itself. Since this is the default action, no
- special handling is normally required, although some programs may wish to
- save the screen state and restore it when they are unsuspended.
-
- #define SIGCONT 19 /* Default action: continue a stopped
- process */
- "You are being restarted after having been suspended." This signal is
- sent by shells to resume a suspended process. If the process is not
- suspended, the signal does nothing. This signal cannot be blocked, but
- it *is* possible to install a handler for it (this is rarely necessary,
- though).
-
- #define SIGCHLD 20 /* Default action: no action taken */
- "One of your children has been suspended or has exited." This signal is
- sent by the kernel to the parent of any process that is terminated (either
- because of a signal or by a Pterm, Pterm0, or Ptermres system call) or
- which is suspended because of a signal. Programs that are concerned with the
- status of their children (for example, shells) may wish to catch this signal;
- after a SIGCHLD has been received, the Pwait3 system call may be
- used to determine exactly which child has exited or been suspended.
- Note that the Psigaction system call may be used to force SIGCHLD to be
- delivered only when a child process terminates (so that suspension of
- child processes, for example via job control, does not raise SIGCHLD.
-
- #define SIGTTIN 21 /* Default action: suspended the process */
- "Attempt to read from a terminal you don't own." This signal is sent to
- any process that attempts to do input from a terminal with a different
- process group than their own. Usually, this happens if the user has started
- the job in the background; the process will be suspended until the user
- explicitly brings it to the foreground with the appropriate shell command
- (at which time the shell will reset the terminal's process group and
- send the stopped process a SIGCONT signal to tell it to continue).
- [NOTE: in fact, SIGTTIN and SIGTTOU are sent to all processes in the same
- process group as the process that attempted to do the i/o; this is for
- compatibility with Unix, and it simplifies the implementation of job
- control shells.]
-
- #define SIGTTOU 22 /* Default action: suspend the process */
- "Attempt to write to a terminal that you don't own." Similar to SIGTTIN (q.v.).
- Processes should normally respect the user's job control and should
- override or ignore SIGTTOU only in situations where a very critical error
- has occured and a message must be printed immediately.
-
- #define SIGXCPU 24
- "Your CPU time limit has been exhausted." Sent to processes when they have
- consumed more than the maximum number of milliseconds of CPU time allowed
- by the Psetlimit() system call. The signal will continue to be sent to
- the process until it exits; if a process does catch this signal, it should
- do whatever clean up actions are necessary and then terminate.
-
- #define SIGWINCH 28 /* Default action: no action taken */
- "The window you were running in has changed size." This signal is sent
- to processes by some window managers to indicate that the user has changed
- the size of the window the process is running in. If the process cares
- about the window size, it may catch this signal and use an Fcntl call
- to inquire about the new window size when the signal is received.
- (See the documentation for Fcntl for details.)
-
- #define SIGUSR1 29
- #define SIGUSR2 30
-
- These two signals are reserved for applications, which may define whatever
- meaning they wish for them. Note, however, that these signals do
- terminate processes by default, so don't send them to a process which
- isn't prepared to deal with them.
-
-
- System Calls Dealing With Signals
-
-
- WORD
- Pkill( WORD pid, WORD sig )
-
- If pid > 0, then the given signal (see the numbers above) is sent to the
- process with that pid.
- If pid == 0, then the given signal is sent to all members of the process
- group of the process making the Pkill call. This includes, of course,
- the process itself.
- If pid < 0, the signal is sent to all members of process group (-pid).
-
- Returns:
- 0 for successful sending of the signal
- (Note that if the current process is a recipient of the signal,
- and the signal proves to be fatal, then Pkill will never return.)
- ERANGE if "sig" is less than 0 or greater than 31
- EFILNF if pid > 0 and the indicated process has terminated or does not
- exist, or if pid < 0 and there are no processes in the given
- process group
- EACCDN if the sending process is not authorized to send signals to
- the specified receiving process or group (for example, they
- belong to different users)
-
-
- #define SIG_DFL (0L)
- #define SIG_IGN (1L)
-
- LONG
- Psignal( WORD sig, LONG handler )
-
- Change the handling of the indicated signal.
-
- If "handler" is SIG_DFL, then the default action for the signal will occur when
- the signal is delivered to the current process.
-
- If "handler" is SIG_IGN, then the signal will be ignored by the process, and
- delivery of the signal will have no noticeable effect (in particular, the
- signal will not interrupt the Pause system call, q.v.). If the signal
- is pending at the time of the Psignal call, it is discarded.
-
- If "handler" is any other value, it is assumed to be the address of a
- user function that will be called when the signal is delivered to the
- process. The user function is called with a single LONG argument on
- the stack, which is the number of the signal being delivered (this is done
- so that processes may use the same handler for a number of different
- signals). While the signal is being handled, it is blocked from delivery;
- thus, signal handling is "reliable" (unlike Version 7 and early System V
- Unix implementations, in which delivery of a second signal while it
- was being handled could kill the process). Also note that, unlike some
- versions of Unix, the signal handling is *not* reset to the default action
- before the handler is called; it remains set to the given signal handler.
-
- The signal handler must either return (via a normal 680x0 rts instruction)
- or call the Psigreturn system call to indicate when signal handling is
- complete; in both cases, the signal will be unblocked. Psigreturn also
- performs some internal clean-up of the kernel stack that is necessary if
- the signal handler is not planning to return (for example, if the C
- longjmp() function is to be used to continue execution at another point
- in the program).
-
- Signal handlers may make any GEMDOS, BIOS, or XBIOS system calls freely.
- GEM AES and VDI calls should not be made in a signal handler.
-
- Note that calling Psignal to change behavior of a signal has the side
- effect of unmasking that signal, so that delivery is possible. This is done
- so that processes may, while handling a signal, reset the behavior and
- send themselves another instance of the signal, for example in order
- to suspend themselves while handling a job control signal.
-
- Signal handling is preserved across Pfork and Pvfork calls. Signals
- that are ignored by the parent are also ignored by the child after a Pexec
- call; signals that were being caught for handling in a function are reset
- in the child to the default behavior.
-
- Returns:
- The old value of handler on success.
- ERANGE if sig < 1 or sig > 31
- EACCDN if sig cannot be caught by the user (i.e. SIGKILL or SIGSTOP)
-
- Bugs:
- Signal handling can be nested only a small (around 3) number of times,
- i.e. if 4 signals are delivered to a process, and the process has established
- handlers for all 4, and none of the handlers has returned or called
- Psigreturn, then there is a very good chance of a stack overflow killing
- the process off. In practice, this is unlikely to happen.
-
-
- LONG
- Psigblock( LONG amask )
-
- Block receipt of some signals. The "amask" argument is added to the
- current set of signals being masked, i.e. the new set of blocked signals
- is the union of the old set and the set represented by amask. Sets of
- blocked signals are represented by a 32 bit unsigned long quantity, with
- bit (1L << sig) set if signal "sig" is to be blocked, and clear if not.
-
- Blocked signals remain blocked across Pfork and Pvfork calls. For Pexec
- calls, children always start out with an empty set of blocked signals,
- regardless of which signals are blocked in the parent.
-
- Returns:
- The old set of blocked signals (i.e. the set as it was before amask
- was added to it).
-
- NOTE: Certain signals (SIGKILL, SIGSTOP, SIGCONT) cannot be blocked;
- if the corresponding bits are set in amask, the kernel will clear them
- but will not report an error.
-
-
- LONG
- Psigsetmask( LONG mask )
-
- Decide which signals are to be blocked from delivery. Unlike Psigblock
- (which adds to the set of blocked signals) Psigsetmask changes the
- entire set, replacing the old set of blocked signals with the one
- specified in "mask". As with Psigblock, signal n is blocked from
- delivery if bit (1L << n) is set in mask. Note that certain signals
- cannot be blocked, and if the corresponding bits are set in the
- mask the kernel will clear them.
-
- Returns:
- The old set of blocked signals.
-
- Usage:
- Typically, Psigblock and Psigsetmask are used together to temporarily
- block signals, e.g.:
-
- oldmask = Psigblock( (1L << SIGINT) );
- ... do some things with SIGINT blocked from delivery ...
- (void) Psigsetmask(oldmask);
-
-
-
- LONG
- Psigpending()
-
- Give an indication of what signals are pending (i.e. have been sent to
- the process but not yet delivered, probably because they are blocked
- from delivery).
-
- Returns:
- A 32 bit unsigned long representing the set of signals that are pending.
- Signal n is pending if bit (1L << n) is set in the returned value.
-
-
- void
- Psigreturn()
-
- Terminate signal handling. This call should be used by any signal
- handler that is not planning to return to the kernel (i.e. if the
- handler is going to execute a non-local jump to another point in the
- program). It cleans up the signal delivery stack and unblocks the
- signal that was being delivered. Calling Psigreturn when no signal
- is being delivered is harmless.
-
- Bugs:
- Calling Psigreturn from a signal handler, and then actually returning
- from that handler, is likely to produce extremely unpleasant results.
- Don't do it.
-
-
- void
- Pause()
-
- Wait until a signal is delivered. This call will return after any (non-fatal)
- signal has been delivered to the process. Note that signals that are being
- ignored are never delivered.
-
-
- void
- Psigpause( LONG mask )
-
- Block the set of signals specified by "mask", and then wait until
- a signal is delivered. This call will return after any (non-fatal)
- signal has been delivered to the process. Before returning, the signal
- mask is restored to its original value.
-
-
-
- struct sigaction {
- LONG sa_handler;
- LONG sa_mask;
- WORD sa_flags;
- #define SA_NOCLDSTOP 1;
- }
-
- WORD
- Psigaction( WORD sig, struct sigaction *act, struct sigaction *act )
-
- Like Psignal, this call changes the handling of the indicated signal.
- If "act" is non-zero, it is a pointer to a structure which describes
- the new signal handling behavior, as follows:
-
- sa_handler is the function to be called when the signal is delivered,
- or SIG_DFL, or SIG_IGN. For further information about
- signal handling functions, see Psignal.
- sa_mask is a set of additional signals to mask while the signal
- is being delivered. The signal itself is always masked,
- but sometimes it might be desireable to mask some
- other signals as well; this allows a "prioritization"
- of signals
- sa_flags extra flags which can affect the behavior of the
- signal. This field should normally be set to 0.
- If "sig" is SIGCHLD and "flags" is SA_NOCLDSTOP,
- then the SIGCHLD signal will not be delivered to
- this process when one of its children are stopped.
-
- If "oact" is non-zero, then the old signal handling behavior is
- copied into "oact" and returned.
-
- Returns:
- 0 on success
- ERANGE if sig < 1 or sig > 31
- EACCDN if sig cannot be caught by the user
-
- Usage:
- If "sig" is a valid signal, the call:
- foo = Psignal(sig, newfunc)
- is equivalent to:
- struct sigaction newact, oact;
- newact->sa_mask=0L;
- newact->sa_flags=0;
- newact->sa_handler = newfunc;
- Psigaction(sig, &newact, &oact);
- foo = oact->sa_handler;
-
-
- LONG
- Talarm( LONG s )
-
- If s > 0, schedule a SIGALRM signal to occur in s seconds. This alarm
- will replace any previously scheduled alarm.
- If s = 0, cancel any previously scheduled alarm.
- If s < 0, inquire about a scheduled alarm but do not change it.
-
- Returns:
- If an alarm was previously scheduled, returns the number of seconds remaining
- until that previously scheduled alarm. Otherwise, returns 0.
-
- Bugs:
- Internal calculations are done in milliseconds, not seconds, so the returned
- value is not exactly accurate.
- For the same reason, setting an alarm more than 2 million seconds or so
- into the future will not work correctly.
-
-
- FIFOs
-
-
- FIFOs are "first in first out" message queues. Pipes are a special kind of
- (unidirectional) FIFO. FIFOs are represented by files in the subdirectory
- "PIPE" on drive "U:." They are created with the Fcreate(name, flags)
- system call. "name" will be the name under which the fifo is known
- (maximum 13 characters); "flags" is explained below. The returned file handle
- is treated just like an ordinary file, and may be written to and read from
- (unless the fifo is unidirectional, in which case it may only be written to).
- The program that creates the FIFO is normally called the "server." Other
- programs ("clients") may use the Fopen(name, mode) system call to open the
- other end of the FIFO and read the data that the server writes, or write data
- for the server to read. When the last program (either client or server) using
- a FIFO closes it, the FIFO is deleted automatically. Note that one program can
- be both client and server, if it creates a FIFO with Fcreate and then opens it
- again with Fopen. Also, children of the server can inherit the Fcreate'd file
- handle and thus have access to the "server" side of the FIFO.
-
- The bits in the "flags" argument to Fcreate have the following meanings:
-
- 0x01
- Make the FIFO unidirectional (server can write, clients can read).
-
- 0x02
- Cause reads to return EOF if no other processes are writing, and writes
- to raise the SIGPIPE signal if no other processes are reading. The
- default action (if this flag is not given) is to block waiting for
- reads and writes.
-
- 0x04
- Make the FIFO a pseudo-tty; to client processes, the FIFO will act
- just like a terminal with the server "typing" the characters; for
- example, if the server writes a control-C, SIGINT will be sent to clients.
- Data can be passed through such a FIFO in long words rather than bytes,
- if the Fputchar() system call is used.
- This allows the server program to pass the extended BIOS information
- (such as the shift key status and scan code) to be returned by Bconin()
- calls on the client side of the FIFO. The 'extra' 3 bytes of the longword
- could also be used for other out of band data.
-
- 0x20
- Make the FIFO support Unix style "read" semantics; i.e. Fread() will
- return as soon as any bytes are available on the FIFO, and will return
- the number of bytes read. If this flag is clear, then Fread() will not
- return until the number of bytes specified in the Fread() call have been
- read, or until there are no more writers on the FIFO.
-
- Attempting to Fcreate() a FIFO with the same name as an already existing
- one will result in an access error (i.e. the Fcreate() will fail).
-
- Pipes may be created through the Fpipe() system call as well as through
- the Fcreate()/Fopen() pair; the former method is easier, since the kernel
- takes care of name conflicts, etc. Pipes created in this way
- will be unidirectional, and will have Unix read semantics.
-
- FIFOs may be locked by processes via the Fcntl() system call, as follows:
-
- /* values for the l_type field */
- #define F_RDLCK 0
- #define F_WRLCK 1
- #define F_UNLCK 3
-
- struct flock {
- short l_type; /* type of lock */
- short l_whence; /* what is the lock relative to? */
- long l_start; /* start of locked region */
- long l_len; /* 0 for "rest of file" */
- short l_pid; /* set by F_GETLK */
- };
- .fi
-
- The "l_whence" field takes a value like the "whence" argument of Fseek():
- zero means "from the beginning," one means "from the current position," and
- two means "from the end." The l_start field is added to the appropriate
- offset in the file and the lock starts there.
-
- Fcntl(fd, &lock, F_SETLK)
- Set a lock as specified by the lock structure.
- The current version of MiNT only understands locks on the whole FIFO,
- so lock.l_start and lock.l_len should both be 0.
- If lock.l_type is F_UNLCK,
- then the lock is released. Otherwise, the whole file is locked
- (future versions of MiNT may distinguish between read and write locks,
- but for now all locks are treated as write locks (F_WRLCK) and block both
- reads and writes). If another process has locked the fifo, the
- Fcntl call returns EACCDN (-36). If a process holding a lock terminates,
- the FIFO is automatically unlocked.
-
- Fcntl(fd, &lock, F_GETLK)
- If a lock exists on the fifo, set lock to
- indicate what kind of lock it is; otherwise, set lock.l_type
- to F_UNLCK.
-
- Locks are only "advisory"; that is, a lock on a file prevents obtaining
- another lock, but does not actually prevent reads and writes.
- Thus, programs may ignore locks if they
- choose to do so. However, if all programs that use a fifo also use locks,
- two clients' data will not be not mixed together in that fifo.
-
- Using FIFOs:
-
- FIFOs are actually very easy to use. Here are some things to keep in mind:
-
- (1) The server program (the one that's going to be listening
- for requests from clients) should create the FIFO with
- Fcreate(). The file descriptor returned from Fcreate() is
- the "server" descriptor; descriptors returned by Fopen() will
- be "client" descriptors. Data written to the server descriptor
- can be read by client descriptors, and vice-versa.
- (2) FIFOs are by default bidirectional. You can create a single
- directional FIFO by creating the fifo "read only"; in this case,
- only the server descriptor can be written to, and only client
- descriptors can be read from.
- (3) Be careful not to mix data up; if two clients are trying to
- read from the same FIFO at the same time, they each may read
- data intended for the other. The easiest way to avoid this is
- by having every client lock the FIFO before accessing it,
- and unlock the FIFO when finished. It's also possible (if you're
- careful) to use the fact that all writes of <1024 bytes are atomic
- (i.e. take place in one "chunk") to avoid interleaving of data;
- but locks are probably safer.
-
- Here is a sample pair of applications. The server program ("fortserv.c")
- creates a FIFO and listens on it for requests. When it receives a
- request, it writes a cute saying (a "fortune cookie") back to the FIFO.
- The client program ("fortune.c") opens the FIFO, writes a request,
- reads the response, and prints the result on the terminal. These are
- very simple minded applications, but it should give you an idea of
- the flavour of how to use FIFOs for interprocess communication.
- -------------------------- fortserv.c -------------------------
- /* fortune server: send cookies to clients */
- /* illustrates server side use of fifos */
-
- /*
- * This program opens a fifo ("U:\PIPE\FORTUNE")
- * and listens to requests on that fifo. When it
- * gets a request (consisting of a single '?'
- * character) it writes back as a reply a 1 byte
- * "length" followed by a randomly selected saying.
- * BUGS:
- * - maximum of 255 characters for a fortune
- * - the fortunes aren't particularly interesting
- */
-
- #ifdef __GNUC__
- #include <minimal.h>
- #endif
- #include <osbind.h>
- #include <mintbind.h>
- #include <string.h>
-
- #define FIFONAME "U:\\PIPE\\FORTUNE"
- #define MAXSIZE 255
-
- /* witty (?) sayings */
-
- char * sayings[] = {
- "Core fault -- program dumped.",
- "Don't worry, be happy!",
- "Help! I'm trapped in a fortune cookie factory!",
- "\"Home is where you wear-a your hat.\"",
- "I want a cookie.",
- "MS-DOS: just say \"no\".",
- "Never play leapfrog with a unicorn.",
- "No matter where you go, there you are.",
- "Sorry, I'm out of short, pithy sayings today.\r\nTry again later.",
- "They say that playing NetHack is like walking into a death trap.",
- "Vision hazy, try again later.",
- "What? You expected something funny?",
- "Why is it that UFO's always seem to visit idiots?",
- "Your puny intellect is no match for our superior weapons.",
- };
- #define NUMSAYINGS (sizeof(sayings) / sizeof(char *))
-
- /* file descriptor for the fortune fifo */
- int fd;
-
-
- /* send a witty saying out through the fifo */
-
- void
- send_saying()
- {
- int i;
- char *s;
- char tmpbuf[MAXSIZE+1];
-
- /* pick a saying at random */
- i = ((unsigned)Random() >> 1) % NUMSAYINGS;
- s = sayings[i];
-
- /* construct the message to send */
- i = (int)strlen(s);
- tmpbuf[0] = i;
- strcpy(tmpbuf+1,s);
-
- /* we really should check for an error */
- (void)Fwrite(fd, (long)i+1, tmpbuf);
- }
-
- /* main function: create the fifo, then sit around
- * listening for requests
- */
-
- int
- main(argc, argv, envp)
- int argc;
- char **argv, **envp;
- {
- char c;
- long r;
-
- fd = Fcreate(FIFONAME, 0);
- if (fd < 0) {
- Cconws("Couldn't create ");
- Cconws(FIFONAME);
- Cconws("!\r\n");
- Pterm(1);
- }
-
- for(;;) {
- r = Fread(fd, 1L, &c);
- if (r != 1) { /* read error?? */
- break;
- }
- if (c == '?') { /* request for saying */
- send_saying();
- }
- /* could have other requests here */
- }
- return 0;
- }
- ------------------------ fortune.c ----------------------
- /* fortune client: get a fortune cookie from
- * the fortune server
- */
-
- /* illustrates client side use of fifos */
-
- #ifdef __GNUC__
- #include <minimal.h>
- #endif
- #include <osbind.h>
- #include <mintbind.h>
-
- #define FIFONAME "U:\\PIPE\\FORTUNE"
- #define BUFSIZ 256
- #define F_SETLKW 7
-
- struct flock {
- short l_type; /* type of lock */
- #define F_RDLCK 0
- #define F_WRLCK 1
- #define F_UNLCK 3
- short l_whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
- long l_start; /* start of locked region */
- long l_len; /* length of locked region */
- short l_pid; /* pid of locking process
- (F_GETLK only) */
- };
-
- int
- main(argc, argv, envp)
- int argc;
- char **argv, **envp;
- {
- int fd;
- char buf[BUFSIZ];
- unsigned char len;
- struct flock lock;
- long r;
-
- /* open the fifo */
- fd = Fopen(FIFONAME, 2);
- if (fd < 0) {
- Cconws("Couldn't open ");
- Cconws(FIFONAME);
- Cconws("!\r\n");
- Pterm(1);
- }
-
- /* get a lock; this makes sure that two fortune
- * programs don't try to send requests and read
- * replys at the same time
- */
-
- lock.l_type = F_WRLCK;
-
- /* lock the whole file -- only thing that makes sense
- * for a fifo
- */
- lock.l_whence = 0;
- lock.l_start = lock.l_len = 0L;
-
- r = Fcntl(fd, &lock, F_SETLKW);
- if (r != 0) {
- Cconws("Couldn't get a lock!\r\n");
- Pterm(r);
- }
-
- /* write the request */
- Fwrite(fd, 1L, "?");
- /* wait for a reply */
- /* the fortune server writes a 1 byte length, followed by
- * the fortune itself
- */
- r = Fread(fd, 1L, &len);
- if (r != 1L || len != Fread(fd, (long)len, buf)) {
- Cconws("Error reading fortune!\r\n");
- Pterm(1);
- }
- buf[len] = 0;
-
- /* unlock the fifo */
-
- lock.l_type = F_UNLCK;
- (void) Fcntl(fd, &lock, F_SETLKW);
-
- Fclose(fd);
-
- /* now write the fortune to the screen */
- Cconws(buf);
- Cconws("\r\n");
-
- return 0;
- }
-
-
- Shared Memory
-
-
- Children created with the Pexec(4,...) or with Pexec(104,...) share all of
- their parent's memory, as do children created with the Pvfork() system call.
- Hence, they may communicate with their parent (or with each other) via
- global variables.
-
- A more general shared memory mechanism is provided by U:\SHM. Files in
- that directory represent blocks of memory. A program may offer to share
- its memory by creating a file in U:\SHM and executing an Fcntl call
- (SHMSETBLK) to associate a block of memory with the file. Other programs
- may then open the file and do a SHMGETBLK call to gain access to that
- memory.
-
- To create a shared memory file, a program uses the Fcreate() call
- to create a file in U:\SHM, e.g.:
-
- fd = Fcreate("U:\\SHM\\MY.SHARE", 0);
-
- It then uses an Fcntl() call to attach a block of memory (previously
- allocated by Malloc() or Mxalloc()) to the file:
-
- blk = Malloc(128L);
- Fcntl(fd, blk, SHMSETBLK);
-
-
- Several things should be noted when creating a shared memory
- file:
-
- (1) The file's attributes must be 0. Read-only shared memory, or
- shared memory with other attributes, is not yet implemented,
- but may be in the future.
-
- (2) Two shared memory files cannot have the same name. An attempt
- to create a new shared memory file with the same name as an
- existing one will fail with an access denied error (EACCDN).
-
- (3) Once the block of memory has been attached to the file, it
- may be accessed by any application that opens the file.
-
- (4) A shared memory file (and associated block) remain allocated
- even after the program which created it terminates. It can be
- deleted (and the associated memory freed) with an Fdelete()
- system call.
-
- (5) The size of the shared memory file will be the actual size
- of the memory block. This may be somewhat larger than the
- size requested in the Malloc or Mxalloc request, due to memory
- rounding.
-
-
- To use a shared memory block, a client application must open
- the file and use the SHMGETBLK Fcntl to gain access to it.
- For example:
-
- fd = Fopen("U:\\SHM\\MY.SHARE", 2);
- blk = Fcntl(fd, 0L, SHMGETBLK);
- Fclose(fd); /* optional -- see below */
-
- Things to note:
-
- (1) The address of the shared memory block is returned by the
- Fcntl() call. NOTE THAT THIS ADDRESS MAY BE DIFFERENT FOR
- DIFFERENT PROGRAMS. That is, a shared memory block that appears
- at address 0x01000100 in one program may appear at address
- 0x0007f000 in another. In particular, shared memory blocks
- should not contain absolute addresses (e.g. pointers).
-
- (2) The extra argument passed to Fcntl() is reserved for future
- expansion; use 0L for now to ensure compatibility with
- future versions of MiNT.
-
- (3) The mode argument in the Fopen() function must be an accurate
- reflection of how the program plans to use the memory; read and
- write access permissions will be enforced in future versions
- of MiNT.
-
- (4) If no SHMSETBLK has been made for the file, a SHMGETBLK Fcntl
- will return a NULL pointer to indicate an error.
-
- (5) If a program is finished with a shared memory block and no
- longer wishes to use it, it should call Mfree() with the address
- of the block (i.e. the address returned by Fcntl(fd, 0L, SHMGETBLK)).
-
- Deleting a Shared Memory File
-
- The Fdelete() system call may be used to delete a shared memory
- file. This will *not* necessarily free the associated memory;
- the memory will actually be freed only after (1) the file has
- been deleted, and (2) all processes using the memory have
- freed the memory, either directly or as a result of the process
- terminating.
-
- Fdelete() will fail if the shared memory file is still open.
- Processes may omit the Fclose() call if they wish this to happen;
- it's a way of informing the process trying to delete the file
- that people are still interested in it. Note that it is *not*
- harmful to allow the Fdelete to occur, since (as noted above)
- the memory will not actually be freed until everyone is finished
- with it; but sometimes it may be useful for programs to know that
- the memory is still in use.
-
-
- Rendezvous
-
-
- The Pmsg() system call provides a simple message based form of IPC. See
- the manual page for Pmsg for further details.
-
-
- Semaphores
-
-
- Semaphores may be created and otherwise accessed via the Psemaphore system
- call. They are a way to control exclusive access to a resource, with true
- blocking if desired. See Psemaphore's manual page for more details.
-
-
-
- MiNT Friendly Programs
-
-
- If you want your program to work well in a multitasking environment,
- you should obey the following rules:
-
- (1) Don't hog memory. Mshrink() your initial TPA as soon as possible after
- starting, and only Malloc() as much memory as you need.
-
- (2) Avoid global changes to the system (e.g. modifying the BIOS keyboard
- maps with Keytbl()); if more than one program tries to modify the
- same resource in incompatible ways, confusion is sure to result.
-
- (3) Use supervisor mode sparingly. In the current implementation, processes
- running in supervisor mode are not preempted, and hence will hog the CPU.
- (You should not rely on this side-effect of supervisor mode; it may go
- away.)
-
- (4) Don't write directly to screen memory; use the documented AES, VDI,
- and BIOS calls for output.
-
- (5) Don't access memory that you don't own, and don't make other programs
- access memory that they aren't allowed to. The latter point means that
- if you install an interrupt handler, or provide a cookie that points to
- data or code in your program, you must make sure that the data or code
- pointed to is in global memory (see Appendix A, Memory Protection, for
- details). Otherwise, when another process tries to access the data or
- code (for example, if an interrupt whose vector you replaced occurs)
- it will receive a bus error.
-
- (6) If you do things in the system like exchanging mouse movement/button
- vectors, then do catch signal 15 (SIGTERM) and other signals that can kill
- your process, and perform cleanup operations in a signal handling routine
- before terminating; this makes it easy for the user to remove your process.
- Otherwise your process can be killed and the vectors you've installed will
- be pointing at empty space.
-
-
- MiNT extensions to GEMDOS calls
-
-
- Fsfirst()/Fsnext()
- MiNT domain processes (see the Pdomain()) man page) get lower case
- filenames from Fsfirst() or Fsnext() on a TOS filesystem. This is because most
- programs end up converting them to lowercase anyway, to be more Unix-like.
- Please don't do this translation yourself. Let MiNT handle it, because
- some filesystems (e.g. the minix one) are case sensitive! If you really,
- truly, prefer uppercase filenames, run in the TOS domain.
-
- Fopen()/Fread()/Fwrite()/Flock()
- MiNT implements the Atari file locking protocol, as described in the
- document "GEMDOS File and Record Locking Specification". If no _FLK
- cookie is installed when MINT.PRG is run, one will be created.
-
- Pexec(100, name, cmdline, environment)
- Similar to Pexec(0, ...), except the calling program does not wait for
- the child to finish. Returns a negative error code, or the (positive)
- process ID of the child.
-
- Pexec(104, name, basepage, 0L)
- Similar to Pexec(4, ...); starts executing a basepage previously
- set up by Pexec() mode 3, 5, or 7. The caller does not wait for
- the child to finish. Returns a negative error code, or the process ID
- of the child. Note that the child's environment and basepage are
- owned by both the child and the parent (indeed, the child shares all
- memory owned by the parent). \name\ is a pointer to a string
- to be used to supply a name for the new process; if it is NULL, then
- the parent's name is used.
-
- Pexec(106, name, basepage, 0L)
- Similar to Pexec(104,...) except that the child's environment and
- basepage are \not\ owned by the parent; nor does the child share
- any memory allocated to the parent. Thus, when the child terminates,
- its memory will be freed. A program loaded with mode 3 and then
- started with mode 106 behaves just like one loaded and started with
- mode 100. In the same way, mode 3 followed by mode 6 is just like mode 0.
-
- Pexec(200, name, cmdline, environment)
- As with Pexec(0,...) and Pexec(100,...) this runs a program. However, with
- this variant the caller is completely replaced with the executing program.
- The process retains its process ID and most other attributes, but all of
- its memory is freed and a new address space is set up for it containing the
- code from the indicated program. Whereas Pexec(0,...) is like a subroutine
- call, Pexec(200,...) is like a "goto." It returns only if an error occurs
- in launching the indicated program (e.g. if not enough memory is available,
- or the file is not found).
-
-
- New MiNT calls
-
-
- This list shows the name, return type, and argument types of the new
- MiNT system calls, and the corresponding function number for Trap #1.
-
- word Syield() [ 0x0ff ]
- word Fpipe( word *ptr ) [ 0x100 ]
- word Fcntl( word f, long arg, word cmd) [ 0x104 ]
- long Finstat( word f ) [ 0x105 ]
- long Foutstat( word f ) [ 0x106 ]
- long Fgetchar(word f, word mode) [ 0x107 ]
- long Fputchar( word f, long c, word mode ) [ 0x108 ]
- long Pwait() [ 0x109 ]
- word Pnice( word delta ) [ 0x10a ]
- word Pgetpid() [ 0x10b ]
- word Pgetppid() [ 0x10c ]
- word Pgetpgrp() [ 0x10d ]
- word Psetpgrp(pid, newgrp) [ 0x10e ]
- word Pgetuid() [ 0x10f ]
- word Psetuid( word id ) [ 0x110 ]
- word Pkill( word pid, word sig ) [ 0x111 ]
- long Psignal(word sig, long handler) [ 0x112 ]
- word Pvfork() [ 0x113 ]
- word Pgetgid() [ 0x114 ]
- word Psetgid(word id) [ 0x115 ]
- long Psigblock(long mask) [ 0x116 ]
- long Psigsetmask(long mask) [ 0x117 ]
- long Pusrval(long arg) [ 0x118 ]
- word Pdomain(word newdom) [ 0x119 ]
- void Psigreturn() [ 0x11a ]
- long Pfork() [ 0x11b ]
- long Pwait3(word flag, long *rusage) [ 0x11c ]
- word Fselect( word timeout, long *rfds, long *wfds, long *xfds )
- [ 0x11d ]
- void Prusage( long r[8] ) [ 0x11e ]
- long Psetlimit(word lim, long value ) [ 0x11f ]
- long Talarm( long secs ) [ 0x120 ]
- void Pause() [ 0x121 ]
- long Sysconf( word n ) [ 0x122 ]
- long Psigpending() [ 0x123 ]
- long Dpathconf( char *name, word n ) [ 0x124 ]
- long Pmsg( word mode, long mbox, void *msg ) [ 0x125 ]
- long Fmidipipe( word pid, word in, word out ) [ 0x126 ]
- word Prenice( word pid, word delta ) [ 0x127 ]
- long Dopendir( char *name, word flag ) [ 0x128 ]
- long Dreaddir( word buflen, long dir, char *buf ) [ 0x129 ]
- long Drewinddir( long dir ) [ 0x12a ]
- long Dclosedir( long dir ) [ 0x12b ]
- long Fxattr( word flag, char *name, void *buf ) [ 0x12c ]
- long Flink( char *oldname, char *newname ) [ 0x12d ]
- long Fsymlink( char *oldname, char *newname ) [ 0x12e ]
- long Freadlink( word siz, char *buf, char *name ) [ 0x12f ]
- long Dcntl( word cmd, char *name, long arg ) [ 0x130 ]
- long Fchown( char *name, word uid, word gid ) [ 0x131 ]
- long Fchmod( char *name, word mode ) [ 0x132 ]
- long Pumask( unsigned word mode ) [ 0x133 ]
- long Psemaphore( word mode, long id, long timeout ) [ 0x134 ]
- word Dlock( word mode, word drive ) [ 0x135 ]
- void Psigpause( long sigmask ) [ 0x136 ]
- long Psigaction( word sig, long act, long oact ) [ 0x137 ]
- long Pgeteuid() [ 0x138 ]
- long Pgetegid() [ 0x139 ]
- long Pwaitpid( word pid, word flag, long *rusage ) [ 0x13a ]
- long Dgetcwd( char *path, word drive, word size ) [ 0x13b ]
- long Salert( char *msg ) [ 0x13c ]
-
-